/*
 * Copyright 2011-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sabayframework.mem.impl.disk;

import java.io.IOException;

import org.sabayframework.mem.Transaction.Status;

public interface DiskTransaction {
	/**
	 * Read data from given address, including record modified in current transaction.
	 * @return byte array with data. Returns byte array with zero length if address 
	 * was not used before.
	 * */
	byte[] read(long address) throws IOException;
	
	/**
	 * Returns true if given addresses were locked.
	 * The lock remains until transaction is completed.
	 * Returns false if attempt to lock the records is failed.
	 * The lock is not enforced in transactions, instead application should not call 
	 * read or update if lock was not obtained.
	 * */
	boolean tryLock(long[] addresses) throws IOException;;

	/**
	 * Replaces or inserts data fragment into the file.
	 * This method may be called multiple times before commit or rollback.
	 * */
	void update(long address, byte[] data) throws IOException;
	/**
	 * Returns an address of a record that is not in use. Next call to the method will 
	 * return a different address.
	 * Returned address will be reserved during period when transaction remains active. 
	 * */
	long getNextAvailableAddress() throws IOException;
	/**
	 * Appends data fragment to the end of the file.
	 * This method may be called multiple times before commit or rollback.
	 * @return address of the data fragment in the file
	 * */
	long insert(byte[] data) throws IOException;
	
	/**
	 * Delete data by given address.
	 * Does nothing if address is not in use.
	 * */
	void delete(long address) throws IOException;
	
	/**
	 * Returns true only if record with given address was modified in the transaction.
	 * */
	boolean hasModified(long address) throws IOException;
	
	/**
	 * Returns addresses of inserted, updates or deleted records
	 * */
	long[] getModified() throws IOException;
	/**
	 * Synchronize write buffers with underlying storage.
	 * This method may be called multiple times before commit or rollback.
	 * */
	void flush() throws IOException;
	/**
	 * Commit changes in the transaction.
	 * */
	void commit() throws IOException;
	/**
	 * Roll back changes in the transaction.
	 * */
	void rollback() throws IOException;
	/**
	 * Returns true if this transaction was not committed or rolled back
	 * */
	boolean isActive() throws IOException;;

	/**
	 * Return true if transaction is in committed state.
	 * */
	boolean isCommitted();
	
	/**
	 * Returns number of milliseconds passed between the moment when transaction
	 * was created and the moment when it was committed or rolled back. If transaction
	 * is still active then it return number of milliseconds passed from transaction 
	 * creation moment. 
	 * */
	long getActiveMillis();

	/**
	 * Returns transaction status.
	 * */
	Status getStatus();
}
